package com.spring.calc.Controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

@RestController
@RequestMapping("/calc")
public class CalcController {
    //历史记录链表
    public List<String> expressionList = new ArrayList<>();

    //获取历史记录链表
    @RequestMapping("/getlist")
    public List<String> getlist(){
        return expressionList;
    }

    //删除历史记录
    @RequestMapping("/deletelist")
    public boolean deleteList(){
        long n = expressionList.size();
        for (int i = 0; i < n; i++) {
            expressionList.remove(i);
        }
        return true;
    }

    //计算表达式，得出结果
    @RequestMapping("/get")
    public float calc(String expreString) {
//        Scanner scanner = new Scanner(System.in);
//        System.out.print("请输入算术表达式: ");
//        String expression = scanner.nextLine().replaceAll("\\s+", "");
        String expression = expreString.replaceAll("\\s+", "");
        try {
            // 转换和求值
            List<String> postfix = infixToPostfix(expression);
            System.out.println("\n后缀表达式: " + String.join(" ", postfix));

            double result = evaluatePostfix(postfix);
            result = (float) (Math.round(result * 100) / 100.0);
            expressionList.add(expression+"="+(float)result);
            System.out.printf("\n计算结果: %.2f\n", result);
            return (float) result;
        } catch (Exception e) {
            throw new IllegalArgumentException("表达式计算错误: " + expreString + " 原因: " + e.getMessage());
        }
    }



    // 运算符优先级
    private static int getPriority(char op) {
        switch (op) {
            case '+':
            case '-': return 1;
            case '*':
            case '/': return 2;
            case '(': return 0; // 左括号在栈内优先级最低
            default: return -1;
        }
    }

    // 判断是否为运算符
    private static boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
    }

    // 中缀转后缀表达式并显示过程
    private static List<String> infixToPostfix(String infix) {
        Stack<Character> stack = new Stack<>();
        Queue<String> output = new LinkedList<>();
        StringBuilder currentNumber = new StringBuilder();
        int step = 1;

        System.out.println("\n中缀转后缀过程:");
        System.out.println("步骤\t当前字符\t栈\t\t队列");

        for (int i = 0; i < infix.length(); i++) {
            char c = infix.charAt(i);

            // 处理数字
            if (Character.isDigit(c)) {
                currentNumber.append(c);
                if (i == infix.length() - 1 || !Character.isDigit(infix.charAt(i + 1))) {
                    output.add(currentNumber.toString());
                    currentNumber.setLength(0);
                }
            }
            // 处理运算符和括号
            else if (isOperator(c)) {
                if (currentNumber.length() > 0) {
                    output.add(currentNumber.toString());
                    currentNumber.setLength(0);
                }

                if (c == '(') {
                    stack.push(c);
                }
                else if (c == ')') {
                    while (!stack.isEmpty() && stack.peek() != '(') {
                        output.add(String.valueOf(stack.pop()));
                    }
                    if (!stack.isEmpty()) stack.pop(); // 弹出 '('
                }
                else {
                    while (!stack.isEmpty() && getPriority(stack.peek()) >= getPriority(c)) {
                        output.add(String.valueOf(stack.pop()));
                    }
                    stack.push(c);
                }
            }
            // 新增：检查非法字符
            else {
                throw new IllegalArgumentException("非法字符: '" + c + "'");
            }

            // 打印当前步骤
            printConversionStep(step++, c, stack, output);
        }

        // 处理剩余数字
        if (currentNumber.length() > 0) {
            output.add(currentNumber.toString());
            printConversionStep(step++, ' ', stack, output);
        }

        // 处理栈中剩余运算符
        while (!stack.isEmpty()) {
            output.add(String.valueOf(stack.pop()));
            printConversionStep(step++, ' ', stack, output);
        }

        return new ArrayList<>(output);
    }

    // 打印转换步骤
    private static void printConversionStep(int step, char current, Stack<Character> stack, Queue<String> output) {
        System.out.printf("%d\t%c\t\t%s\t\t%s\n",
                step,
                current == ' ' ? ' ' : current,
                stack.toString().replace(" ", ""),
                String.join(" ", output).replace(" ", "")
        );
    }

    // 计算后缀表达式并显示过程
    private static double evaluatePostfix(List<String> postfix) {
        Stack<Double> stack = new Stack<>();
        int step = 1;

        System.out.println("\n计算后缀表达式过程:");
        System.out.println("步骤\t当前元素\t操作栈");

        for (String token : postfix) {
            if (token.matches("\\d+")) {
                stack.push(Double.parseDouble(token));
            } else {
                double b = stack.pop();
                double a = stack.pop();
                switch (token) {
                    case "+": stack.push(a + b); break;
                    case "-": stack.push(a - b); break;
                    case "*": stack.push(a * b); break;
                    case "/":
                        if (b == 0) throw new ArithmeticException("除零错误");
                        stack.push(a / b);
                        break;
                }
            }
            printEvaluationStep(step++, token, stack);
        }
        return stack.pop();
    }

    // 打印求值步骤
    private static void printEvaluationStep(int step, String token, Stack<Double> stack) {
        System.out.printf("%d\t%s\t\t%s\n",
                step,
                token,
                stack.toString().replace(" ", "")
        );
    }
}
